<#assign classNameLower = ClassName ? uncap_first>
package ${pPackage}.shiro;

import ${pPackage}.shiro.realm.UserRealm;
import ${pPackage}.shiro.session.CustomSessionManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 自定义shiro配置
 */
@Configuration
public class ShiroConfiguration {

  //创建realm
  @Bean
  public UserRealm getRealm() {
    return new UserRealm();
  }

  //创建安全管理器
  @Bean
  public DefaultWebSecurityManager getSecurityManager(UserRealm realm) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(realm);

    //将自定义的会话管理器注册到安全管理器中
    securityManager.setSessionManager(sessionManager());
    //将自定义的redis缓存管理器注册到安全管理器中
    securityManager.setCacheManager(cacheManager());

    return securityManager;
  }

  //配置shiro的过滤器工厂

  /**
   * 再web程序中，shiro进行权限控制全部是通过一组过滤器集合进行控制
   */
  @Bean
  public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
    //创建过滤器工厂
    ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
    //设置安全管理器
    filterFactory.setSecurityManager(securityManager);
    //通用配置（跳转登录页面，未授权跳转的页面）
    filterFactory.setLoginUrl("/api/autherror?code=1");//跳转url地址
    filterFactory.setUnauthorizedUrl("/api/autherror?code=2");//未授权的url
    //设置过滤器集合
    Map<String, String> filterMap = new LinkedHashMap<>();
    //anon -- 匿名访问
    filterMap.put("/api/${classNameLower}/login", "anon");
    filterMap.put("/api/faceLogin/**", "anon");
    filterMap.put("/api/autherror", "anon");

    // 接口文档访问
    filterMap.put("/swagger-resources", "anon");
    filterMap.put("/v2/api-docs", "anon");
    filterMap.put("/v2/api-docs-ext", "anon");
    filterMap.put("/doc.html", "anon");
    filterMap.put("/webjars/** ", "anon");

    //注册
    //authc -- 认证之后访问（登录）
    filterMap.put("/**", "authc");
//    filterMap.put("/**", "anon");
    //perms -- 具有某中权限 (使用注解配置授权)
    filterFactory.setFilterChainDefinitionMap(filterMap);

    return filterFactory;
  }

  @Value("${r'${spring.redis.host}'}")
  private String host;

  @Value("${r'${spring.redis.port}'}")
  private int port;

  /**
   * redis的控制器，操作redis
   */
  public RedisManager redisManager() {
    RedisManager redisManager = new RedisManager();
    redisManager.setHost(host);
    redisManager.setPort(port);
    return redisManager;
  }

  /**
   * sessionDao
   */
  public RedisSessionDAO redisSessionDAO() {
    RedisSessionDAO sessionDAO = new RedisSessionDAO();
    sessionDAO.setRedisManager(redisManager());
    return sessionDAO;
  }

  /**
   * 会话管理器
   */
  public DefaultWebSessionManager sessionManager() {
    CustomSessionManager sessionManager = new CustomSessionManager();
    sessionManager.setSessionDAO(redisSessionDAO());
    //禁用cookie
    sessionManager.setSessionIdCookieEnabled(false);
    //禁用url重写   url;jsessionid=id
    sessionManager.setSessionIdUrlRewritingEnabled(false);
    return sessionManager;
  }

  /**
   * 缓存管理器
   */
  public RedisCacheManager cacheManager() {
    RedisCacheManager redisCacheManager = new RedisCacheManager();
    redisCacheManager.setRedisManager(redisManager());
    return redisCacheManager;
  }


  //开启对shior注解的支持
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(securityManager);
    return advisor;
  }
}
